package com.ynet.middleground.approve.listener.realistic;

import java.util.ArrayList;
import java.util.List;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import com.ynet.middleground.approve.cmd.SpringContextUtils;
import com.ynet.middleground.approve.constant.WorkflowConstants;
import com.ynet.middleground.approve.listener.BaseListener;
import com.ynet.middleground.approve.model.UserCenterModel;

/**
 * @ClassName
 * @Description 具象化审批-场景一监听器；
 * @Author liwq
 * @Date 2021/1/25 11:27
 * @Version 1.0
 */
@Component
@DependsOn("springContextUtils")
public class FlowStarterIsApproverListener extends BaseListener implements TaskListener {
    private TaskService taskService = SpringContextUtils.getBean(TaskService.class);
    private HistoryService historyService = SpringContextUtils.getBean(HistoryService.class);
    private UserCenterModel userCenterModel = SpringContextUtils.getBean(UserCenterModel.class);
    private RepositoryService repositoryService = SpringContextUtils.getBean(RepositoryService.class);

    /**
     * 流审批节点的审批人若包含发起人，则该审批节点的审批人就默认为发起人，该节点的其他审批人不可审批
     *
     * @param delegateTask
     */
    @Override
    public void notify(DelegateTask delegateTask) {
        // Step1：初步整理所需参数
        // processDefinitionId
        String processDefinitionId = delegateTask.getProcessDefinitionId();
        // taskDefinitionKey
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        // 流程实例ID
        String processInstanceId = delegateTask.getProcessInstanceId();
        // 发起人是否在配置之内 标记
        Boolean includeStarterFlag = false;
        // 流程配置的 任务审批人
        String assignee = delegateTask.getAssignee();
        // 流程配置的 任务处理候选人列表
        List<String> candidateUsers = new ArrayList<>(10);
        // 流程配置的 任务处理候选组列表
        List<String> candidateGroups = new ArrayList<>(10);
        // 整理出 任务处理候选人列表 和 任务处理候选组列表
        for (IdentityLink identityLink : delegateTask.getCandidates()) {
            if ("candidate".equals(identityLink.getType())) {
                if (null != identityLink.getUserId()) {
                    candidateUsers.add(identityLink.getUserId());
                } else if (null != identityLink.getGroupId()) {
                    candidateGroups.add(identityLink.getGroupId());
                }
            }
        }

        // Step2：判断是否会签，会签的话，就不做处理
        Boolean isCounterSign = isCounterSign(processDefinitionId, taskDefinitionKey);
        if (!isCounterSign) {
            // Step3:判断流程发起人，是否属于该任务节点设置的：任务处理人/任务处理候选人列表/任务处理人候选组列表
            // Step3.1: 获取流程发起人
            HistoricProcessInstance processInstance =
                historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            String startUserId = processInstance.getStartUserId();

            // step3.2: 若指定了流程审批人，则不做处理
            if (StringUtils.isEmpty(assignee)) {
                // step3.3: 判断流程发起人 是否属于配置的任务处理候选人列表
                if (candidateUsers.size() > 0) {
                    if (candidateUsers.contains(startUserId)) {
                        includeStarterFlag = true;
                    }
                }
                // step3.4: 判断流程发起人 是否属于配置的任务处理人候选组列表
                if (!includeStarterFlag) {
                    if (candidateGroups.size() > 0) {
                        // 获取发起人的角色部门信息
                        String channel = getChannel(delegateTask);
                        List<String> groupIds = userCenterModel.listUserGroupsByUserId(startUserId, channel,
                            Integer.parseInt(startUserId), null);
                        // 判断发起人的角色部门信息是否在配置的角色信息之内
                        includeStarterFlag = checkIfContains(candidateGroups, groupIds);
                    }
                }

                // Step4: 根据步骤3的判断结果，设置审批人为发起人
                if (includeStarterFlag) {
                    taskService.setAssignee(delegateTask.getId(), startUserId);
                }
            }
        }
    }

    /**
     * 判断发起人的角色部门信息是否在配置的角色信息之内
     * 
     * @param candidateGroups
     * @param groupIds
     * @return true是；false否
     */
    private Boolean checkIfContains(List<String> candidateGroups, List<String> groupIds) {
        for (String s : groupIds) {
            if (candidateGroups.contains(s)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否为会签
     * 
     * @param processDefinitionId
     * @param taskDefinitionKey
     * @return true是；false否
     */
    private Boolean isCounterSign(String processDefinitionId, String taskDefinitionKey) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        Process process = bpmnModel.getProcesses().get(0);
        UserTask userTask = (UserTask)process.getFlowElement(taskDefinitionKey);
        if (userTask.getLoopCharacteristics() == null) {
            return false;
        }
        return true;
    }

}
